/**
 * 
 */
package com.gp.base.security;

import java.util.Collection;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.ServletContext;

import org.springframework.beans.factory.InitializingBean;
import org.springframework.security.ConfigAttributeDefinition;
import org.springframework.security.ConfigAttributeEditor;
import org.springframework.security.intercept.web.FilterInvocation;
import org.springframework.security.intercept.web.FilterInvocationDefinitionSource;
import org.springframework.security.util.AntUrlPathMatcher;
import org.springframework.security.util.RegexUrlPathMatcher;
import org.springframework.security.util.UrlMatcher;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.gp.sys.manager.SysResourceManager;
import com.gp.sys.manager.SysUserManager;
import com.opensymphony.oscache.base.NeedsRefreshException;
import com.opensymphony.oscache.general.GeneralCacheAdministrator;

/**
 * @author Downpour
 */
public class SecureResourceFilterInvocationDefinitionSource implements FilterInvocationDefinitionSource, InitializingBean {
	
	public static GeneralCacheAdministrator cacheAdmin  = new GeneralCacheAdministrator();
	
    private UrlMatcher urlMatcher;

    private boolean useAntPath = true;
    
    private boolean lowercaseComparisons = true;
    
   
    public void setUseAntPath(boolean useAntPath) {
        this.useAntPath = useAntPath;
    }
    
   
    public void setLowercaseComparisons(boolean lowercaseComparisons) {
        this.lowercaseComparisons = lowercaseComparisons;
    }
   
    public void afterPropertiesSet() throws Exception {
        
        // default url matcher will be RegexUrlPathMatcher
        this.urlMatcher = new RegexUrlPathMatcher();
        
        if (useAntPath) {  // change the implementation if required
            this.urlMatcher = new AntUrlPathMatcher();
        }
        
        // Only change from the defaults if the attribute has been set
        if ("true".equals(lowercaseComparisons)) {
            if (!this.useAntPath) {
                ((RegexUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(true);
            }
        } else if ("false".equals(lowercaseComparisons)) {
            if (this.useAntPath) {
                ((AntUrlPathMatcher) this.urlMatcher).setRequiresLowerCaseUrl(false);
            }
        }
        
    }
    
    /**
     * 
     * <li>方法名：getAttributes
     * <li>@param filter
     * <li>@return
     * <li>@throws IllegalArgumentException
     * <li>说明：InitializingBean方法
     * <li>创建人：曾明辉
     * <li>创建日期：2011-3-12
     * <li>修改人： 
     * <li>修改日期：
     */
    public ConfigAttributeDefinition getAttributes(Object filter) throws IllegalArgumentException {
        
        FilterInvocation filterInvocation = (FilterInvocation) filter;
        String requestURI = filterInvocation.getRequestUrl();
        Map<String, String> urlAuthorities = this.getUrlAuthorities(filterInvocation);//获得URL资源
        
        String grantedAuthorities = null;
        for(Iterator<Map.Entry<String, String>> iter = urlAuthorities.entrySet().iterator(); iter.hasNext();) {
            Map.Entry<String, String> entry = iter.next();
            String url = entry.getKey();
            
            if(urlMatcher.pathMatchesUrl(url, requestURI)) {
                grantedAuthorities = entry.getValue();
                break;
            }            
        }
        
        if(grantedAuthorities != null) {
            ConfigAttributeEditor configAttrEditor = new ConfigAttributeEditor();
            configAttrEditor.setAsText(grantedAuthorities);
            return (ConfigAttributeDefinition) configAttrEditor.getValue();
        }
        
        return null;
    }

   
    @SuppressWarnings("unchecked")
	public Collection getConfigAttributeDefinitions() {
        return null;
    }

   
    @SuppressWarnings("unchecked")
	public boolean supports(Class clazz) {
        return true;
    }
    
   
    /**
     * 
     * <li>方法名：getUrlAuthorities
     * <li>@param filterInvocation
     * <li>@return
     * <li>返回类型：Map<String,String>
     * <li>说明：得到URL资源，使用了OSCache
     * <li>创建人：曾明辉
     * <li>创建日期：2011-3-12
     * <li>修改人： 
     * <li>修改日期：
     */
    @SuppressWarnings("unchecked")
	private Map<String, String> getUrlAuthorities(FilterInvocation filterInvocation) {
    	Map<String, String> urlAuthorities = null;
    	String key = "urlAuthorityKey";
    	
		try{
			urlAuthorities = (Map<String, String> ) cacheAdmin.getFromCache(key, 3600);
		}catch (NeedsRefreshException nre){//无数据或过期
			System.out.println("需要更新URL资源");
			try{		  
				ServletContext servletContext = filterInvocation.getHttpRequest().getSession().getServletContext();
	      
				SysResourceManager resourceManager = (SysResourceManager)WebApplicationContextUtils.getWebApplicationContext(servletContext).getBean("sysResourceManager"); 
				
				urlAuthorities = resourceManager.loadUrlAuthorities();
				cacheAdmin.putInCache(key, urlAuthorities);//在缓存中存储
			}catch (Exception ex) {//取不了数据
				urlAuthorities = (Map<String, String> )  nre.getCacheContent();//原来的数据
				cacheAdmin.cancelUpdate(key);          //取消更新，避免阻塞
			}
		}
		
    	return urlAuthorities;
    }

}
